package com.su.bo.process.util

import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import org.dom4j.DocumentHelper
import org.dom4j.Element
import com.su.bo.process.util.JsonInject.inject
import java.util.function.Consumer

@Suppress("unused")
object JsonToXml {
    /**
     * 特殊处理如果生成的Xml中含有命名空间则先进性命名空间的填充。
     * @param json 源数据Json
     * @return 转换后的Xml
     */
    @JvmStatic
    fun toXmlByJson(json: String?): StringBuffer {
        val document = DocumentHelper.createDocument()
        document.rootElement = document.addElement("root")
        val rootElement = getXml(inject(json), document.rootElement, null)
        val stringBuffer = StringBuffer()
        rootElement.elements().forEach(Consumer { element: Element -> stringBuffer.append(element.asXML()) })
        return stringBuffer
    }

    @JvmStatic
    private fun getXml(jsonElement: JsonElement, parentElement: Element, name: String?): Element {
        when (jsonElement) {
            is JsonArray -> {
                for (element in jsonElement)
                    getXml(element, parentElement, name)
            }

            is JsonObject -> {
                var currentElement: Element? = null
                if (name != null) {
                    if (name.isNotEmpty()) {
                        if (name.matches(Regex("^.*:.*"))) {
                            val nameSpaceJsonElement = jsonElement.get("@xmlns:" + name.substring(0, name.indexOf(":")))
                            if (nameSpaceJsonElement !== null) {
                                currentElement = parentElement.addElement(name, nameSpaceJsonElement.asString)
                            }
                        }
                        currentElement = currentElement ?: parentElement.addElement(name)
                    }
                }
                for (entity in jsonElement.entrySet()) {
                    if (entity.key.matches(Regex("^@.*"))) {
                        currentElement?.addAttribute(entity.key.substring(1), jsonElement[entity.key].asString)
                        continue
                    }
                    getXml(entity.value, currentElement ?: parentElement, entity.key)
                }
            }
            //说明是一个键值对的key,可以作为节点插入了
            else -> parentElement.addElement(name).addText(jsonElement.asString)
        }
        return parentElement
    }
}
